import { getSession } from '@/lib/auth';
import { db } from '@/lib/db';
import { order, shop } from '@/lib/db/schema/common';
import type { orderStatusValues } from '@/lib/db/schema/enum';
import redis, { genNewOrderNotOnlineKey } from '@/lib/redis';
import { result } from '@/lib/utils';
import { and, between, desc, eq, ilike, inArray } from 'drizzle-orm';
import { BizError, ErrorCode } from '../error';
import type { Pagination } from '../type/pagination';
import type { NewOrderNotification } from '../type/socket';

export const listShopOrdersByPage = async (args: {
  page: number;
  pageSize: number;
  id?: number;
  name?: string;
  phone?: string;
  address?: string;
  status?: (typeof orderStatusValues)[number][];
  dateRange?: {
    from: Date;
    to?: Date;
  };
}) => {
  try {
    const session = await getSession();
    if (!session?.user)
      throw new BizError(ErrorCode.Unauthorized, '用户未登录');
    const res = await db
      .select({
        id: order.id,
        name: order.userName,
        phone: order.userPhone,
        address: order.address,
        status: order.status,
        createdAt: order.createdAt,
      })
      .from(order)
      .innerJoin(shop, eq(shop.id, order.shopId))
      .where(
        and(
          eq(shop.userId, session.user.id),
          args.id !== undefined ? eq(order.id, args.id) : undefined,
          args.name !== undefined
            ? ilike(order.userName, `%${args.name}%`)
            : undefined,
          args.phone !== undefined
            ? ilike(order.userPhone, `%${args.phone}%`)
            : undefined,
          args.address !== undefined
            ? ilike(order.address, `%${args.address}%`)
            : undefined,
          args.status !== undefined
            ? inArray(order.status, args.status)
            : undefined,
          args.dateRange !== undefined
            ? between(
                order.createdAt,
                args.dateRange.from,
                args.dateRange.to ?? new Date(),
              )
            : undefined,
        ),
      )
      .orderBy(desc(order.createdAt))
      .limit(args.pageSize + 1)
      .offset((args.page - 1) * args.pageSize);
    if (res.length > args.pageSize) {
      res.pop();
      return result({
        data: res,
        next: args.page + 1,
      } satisfies Pagination<(typeof res)[0]>);
    }
    return result({ data: res, next: null } satisfies Pagination<
      (typeof res)[0]
    >);
  } catch (error) {
    return result(error, '获取订单失败');
  }
};

export const getOrderById = async (id: number) => {
  try {
    const res = await db.query.order.findFirst({
      where: (order, { eq }) => eq(order.id, id),
      with: {
        shop: true,
      },
    });
    if (!res) throw new BizError(ErrorCode.NotFound, '订单不存在');
    return result(res);
  } catch (error) {
    return result(error, '获取订单失败');
  }
};

export const listUserOrdersByPage = async (args: {
  page: number;
  pageSize: number;
  shopName?: string;
  status?: (typeof orderStatusValues)[number][];
  dateRange?: {
    from: Date;
    to?: Date;
  };
}) => {
  try {
    const session = await getSession();
    if (!session?.user)
      throw new BizError(ErrorCode.Unauthorized, '用户未登录');
    const shops =
      args.shopName !== undefined
        ? await db.query.shop.findMany({
            columns: { id: true },
            where: (shop, { ilike }) => ilike(shop.name, `%${args.shopName}%`),
          })
        : undefined;
    const res = await db.query.order.findMany({
      where: (order, { eq, and, inArray, between }) =>
        and(
          eq(order.userId, session.user.id),
          shops !== undefined
            ? inArray(
                order.shopId,
                shops.map((shop) => shop.id),
              )
            : undefined,
          args.status !== undefined
            ? inArray(order.status, args.status)
            : undefined,
          args.dateRange !== undefined
            ? between(
                order.createdAt,
                args.dateRange.from,
                args.dateRange.to ?? new Date(),
              )
            : undefined,
        ),
      with: {
        shop: {
          with: {
            products: true,
          },
        },
      },
      orderBy: desc(order.createdAt),
      offset: (args.page - 1) * args.pageSize,
      limit: args.pageSize + 1,
    });
    if (res.length > args.pageSize) {
      res.pop();
      return result({
        data: res,
        next: args.page + 1,
      } satisfies Pagination<(typeof res)[0]>);
    }
    return result({ data: res, next: null } satisfies Pagination<
      (typeof res)[0]
    >);
  } catch (error) {
    return result(error, '获取订单失败');
  }
};

export const getNewOrderNotification = async () => {
  try {
    const session = await getSession();
    if (!session?.user)
      throw new BizError(ErrorCode.Unauthorized, '用户未登录');
    const keys = await redis.keys(
      genNewOrderNotOnlineKey({
        userId: '*',
        shopUserId: session.user.id,
      }),
    );
    const data: NewOrderNotification[] = [];
    for (const key of keys) {
      const dataJSON = await redis.get(key);
      const dataArr = JSON.parse(dataJSON || '[]');
      data.push(...dataArr);
      redis.del(key);
    }
    return result(data);
  } catch (error) {
    return result(error, '获取新订单通知失败');
  }
};
